 #include "historymessagewidget.h"

#include <QApplication>
#include <QBuffer>
#include <QDateTimeEdit>
#include <QGridLayout>
#include <QImageReader>
#include <QLabel>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollArea>
#include <QTextEdit>
#include <QFileDialog>

#include "model/datacenter.h"
#include "utils/widgetuitl.hpp"
#include "debug.h"
#include "speechrecorder.h"
#include "toast.h"

/* =========================================== *
 *           历史消息界面窗口实现                 *
 * =========================================== */
HistoryMessageWidget::HistoryMessageWidget(QWidget* parent) : QDialog(parent)
{
    // 1.设置窗口基本属性
    this->setFixedSize(600, 600);
    this->setWindowTitle("历史消息");
    this->setWindowIcon(QIcon(":/resource/image/logo.png"));
    this->setStyleSheet("QWidget { background-color: rgb(255, 255, 255); }");
    this->setAttribute(Qt::WA_DeleteOnClose);

    // 2.网格布局器
    QGridLayout* layout = new QGridLayout();
    layout->setVerticalSpacing(10);
    layout->setHorizontalSpacing(8);
    layout->setContentsMargins(30, 10, 30, 10);
    this->setLayout(layout);

    // 2-1.查询方式单旋按钮
    keyRadioBtn = new QRadioButton("按关键词查询");
    timeRadioBtn = new QRadioButton("按时间查询");
    keyRadioBtn->setChecked(true);                  // 默认按关键词查询
    layout->addWidget(keyRadioBtn, 0, 0, 1, 2);     // 两个按钮各占两列
    layout->addWidget(timeRadioBtn, 0, 2, 1, 2);

    // 2-2 搜索框 && 搜索按钮
    searchEdit = new QLineEdit();
    searchEdit->setFixedHeight(40);
    searchEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    searchEdit->setPlaceholderText("要搜索的关键字");
    searchEdit->setStyleSheet("QLineEdit { border: none; border-radius: 10px; background-color: rgb(240, 240, 240); "
                              "padding-left: 10px; font-size: 16px; }");

    QPushButton* searchBtn = new QPushButton();
    searchBtn->setFixedSize(40, 40);
    searchBtn->setIcon(QIcon(":/resource/image/search.png"));
    searchBtn->setIconSize(QSize(25, 25));
    QString style = "QPushButton { background-color: rgb(240, 240, 240); border: none; border-radius: 10px;} "
                    "QPushButton:hover { background-color: rgb(220, 220, 220); } "
                    "QPushButton:pressed { background-color: rgb(206, 206, 206); }";
    searchBtn->setStyleSheet(style);

    layout->addWidget(searchEdit, 1, 0, 1, 9);
    layout->addWidget(searchBtn, 1, 9, 1, 1);

    // 2-3 空白区填充
    QLabel* spaceLabel = new QLabel();
    spaceLabel->setFixedWidth(10);

    // 3.时间相关控件, 默认状态下隐藏
    QLabel* beginKey = new QLabel("开始时间");
    QLabel* endKey = new QLabel("结束时间");
    beginKey->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
    endKey->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
    beginTimeEdit = new QDateTimeEdit();
    endTimeEdit = new QDateTimeEdit();
    beginTimeEdit->setFixedHeight(40);
    endTimeEdit->setFixedHeight(40);
    beginKey->hide();
    endKey->hide();
    beginTimeEdit->hide();
    endTimeEdit->hide();
    spaceLabel->hide();

    // 4. 创建滚动区
    initScrollArea(layout);

    // 5.查询方式单选框信号处理
    connect(keyRadioBtn, &QRadioButton::clicked, this, [=](){
        layout->removeWidget(beginKey);
        layout->removeWidget(endKey);
        layout->removeWidget(beginTimeEdit);
        layout->removeWidget(endTimeEdit);
        layout->removeWidget(spaceLabel);

        beginKey->hide();
        endKey->hide();
        beginTimeEdit->hide();
        endTimeEdit->hide();
        spaceLabel->hide();

        layout->addWidget(searchEdit, 1, 0, 1, 9);
        searchEdit->show();
    });

    connect(timeRadioBtn, &QRadioButton::clicked, this, [=](){
        layout->removeWidget(searchEdit);
        searchEdit->hide();

        layout->addWidget(beginKey, 1, 0, 1, 1);
        layout->addWidget(beginTimeEdit, 1, 1, 1, 3);
        layout->addWidget(spaceLabel, 1, 4, 1, 1);
        layout->addWidget(endKey, 1, 5, 1, 1);
        layout->addWidget(endTimeEdit, 1, 6, 1, 3);
        beginKey->show();
        endKey->show();
        beginTimeEdit->show();
        endTimeEdit->show();
        spaceLabel->show();
    });

    connect(searchBtn, &QRadioButton::clicked, this, &HistoryMessageWidget::onClickedBySearchBtn);

////////// 构造测试数据
#if TEST_UI
    for (int i = 0; i < 30; i++) {
        model::UserInfo sender;
        sender.userId = "";
        sender.nickname = "小美" + QString::number(i);
        sender.avatar = QIcon(":/resource/image/girl.jpg");
        sender.description = "";
        sender.phone = "";
        model::Message msg = model::Message::makeMessage(model::TEXT_TYPE, "", sender, QString("this is a test message.this is a test message.this is a test message.this is a test message.this is a test message.this is a test message.").toUtf8());
        addHistoryMessage(msg);
    }
#endif
}

void HistoryMessageWidget::addHistoryMessage(const model::Message& message)
{
    HistoryMessageItem* historyMessageItem = HistoryMessageItem::makeHistoryMessageItem(message);
    container->layout()->addWidget(historyMessageItem);
}

void HistoryMessageWidget::clear()
{
    QVBoxLayout* layout = dynamic_cast<QVBoxLayout*>(container->layout());
    for (int i = layout->count() - 1; i >= 0; --i) {
        QLayoutItem* item = layout->takeAt(i);
        if (!item || !item->widget()) {
            continue;
        }
        item->widget()->deleteLater();
    }
}

void HistoryMessageWidget::initScrollArea(QGridLayout* layout)
{
    QScrollArea* scrollArea = utils::WidgetUtil::createQScrollArea();
    container = new QWidget();
    scrollArea->setWidget(container);

    QVBoxLayout* containerLayout = new QVBoxLayout();
    containerLayout->setSpacing(10);
    containerLayout->setContentsMargins(0, 0, 0, 0);
    container->setLayout(containerLayout);

    layout->addWidget(scrollArea, 2, 0, 1, 10);
}

void HistoryMessageWidget::onClickedBySearchBtn()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    connect(dataCenter, &model::DataCenter::searchMessageDone, this, &HistoryMessageWidget::searchMessageDoneHandle, Qt::UniqueConnection);

    if(keyRadioBtn->isChecked()) {
        const QString& key = searchEdit->text();
        if(key.isEmpty()) {
            return;
        }
        dataCenter->searchMessageAsync(key);
    } else {
        QDateTime begin = beginTimeEdit->dateTime();
        QDateTime end = endTimeEdit->dateTime();
        if(begin > end) {
            Toast::showMessage("无法搜索！起始时间大于结束时间");
            this->clear();
            return;
        }
        dataCenter->searchMessageByTimeAsync(begin, end);
    }
}

void HistoryMessageWidget::searchMessageDoneHandle()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::Message>* searchMessageResult = dataCenter->getSearchMessageResult();
    if(!searchMessageResult) {
        return;
    }

    this->clear();

    for(const auto& msg : *searchMessageResult) {
        this->addHistoryMessage(msg);
    }
}



/* =========================================== *
 *           历史消息元素控件实现                 *
 * =========================================== */
HistoryMessageItem::HistoryMessageItem() {}

HistoryMessageItem* HistoryMessageItem::makeHistoryMessageItem(const model::Message& message)
{
    HistoryMessageItem* item = new HistoryMessageItem();
    item->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);    // 高度自由控制

    // 创建网格布局历史消息控件
    QGridLayout* layout = new QGridLayout();
    layout->setVerticalSpacing(0);
    layout->setHorizontalSpacing(10);
    layout->setContentsMargins(0, 0, 0, 5);     // 每条消息之间留5px间距
    item->setLayout(layout);

    // 头像
    QPushButton* avatarBtn = new QPushButton();
    avatarBtn->setFixedSize(40, 40);
    avatarBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    avatarBtn->setIconSize(QSize(40, 40));
    avatarBtn->setIcon(message.sender.avatar);
    avatarBtn->setStyleSheet("QPushButton { border: none; }");

    // 昵称
    QLabel* nameLabel = new QLabel();
    nameLabel->setText(message.sender.nickname + " | " + message.time);
    nameLabel->setFixedHeight(20);
    nameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 消息正文
    QWidget* messageContent = nullptr;
    if (message.messageType == model::MessageType::TEXT_TYPE) {
        QLabel* label = new QLabel();
        label->setFixedWidth(470);
        label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
        label->setWordWrap(true);   // 自动换行
        label->setText(QString(message.content));

        QFontMetrics metrics(label->font());
        QRect textRect = metrics.boundingRect(
            0, 0, label->width(), 0,
            Qt::TextWordWrap | Qt::AlignLeft,
            label->text()
        );
        int lineHeight = metrics.lineSpacing();            // 单行文本的实际行高（包含行间距）
        int actualLines = textRect.height() / lineHeight;

        label->setFixedHeight(16 * actualLines + 2);
        label->setContentsMargins(0, 2, 0, 0);   //通过文本框内自身的边距来控制与nameLabel的间距

        messageContent = label;
    } else if (message.messageType == model::MessageType::IMAGE_TYPE) {
        layout->setVerticalSpacing(2);
        messageContent = new ImageMessageItem(message.fileId, message.content);
    } else if (message.messageType == model::MessageType::FILE_TYPE) {
        messageContent = new FileMessageItem(message.fileId, message.content, message.fileName);
    } else if (message.messageType == model::MessageType::SPEECH_TYPE) {
        messageContent = new SpeechMessageItem(message.fileId, message.content);
    } else {
        LOG(LL_ERROR, "错误的 messageType: {}", message.messageType);
    }

    layout->addWidget(avatarBtn, 0, 0, 2, 1);
    layout->addWidget(nameLabel, 0, 1, 1, 1);
    layout->addWidget(messageContent, 1, 1, 5, 1);

    return item;
}


/* ====================================== *
 *           图片消息类接口实现              *
 * ====================================== */
ImageMessageItem::ImageMessageItem(const QString& fileId, const QByteArray& content)
    : fileId(fileId), imageLoaded(false)
{
    this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    this->setStyleSheet("QPushButton { border: none; }");

    if(content.isEmpty()) {
        model::DataCenter* dataCenter = model::DataCenter::getInstance();
        connect(dataCenter, &model::DataCenter::getSingleFileDone, this, &ImageMessageItem::getSingleFileDoneHandle);
        dataCenter->getSingleFileAsync(fileId);
    } else {
        this->loadImage(content);
    }
}

void ImageMessageItem::getSingleFileDoneHandle(const QString& fileId, const QByteArray& content)
{
    if(this->fileId != fileId) {
        return;
    }
    this->loadImage(content);
}

void ImageMessageItem::loadImage(const QByteArray& imageData)
{
    if (imageLoaded) return; // 防止重复加载

    // 1. 使用QImageReader自动处理EXIF旋转, 加载图像
    QBuffer buffer(const_cast<QByteArray*>(&imageData));
    buffer.open(QIODevice::ReadOnly);
    QImageReader reader(&buffer);
    reader.setAutoTransform(true);
    image = reader.read();

    // 2.消息展示区中的图片缩放
    updateImageSize();

    // QImage无法直接生成QIcon, 转成QPixmap
    QPixmap pixmap = QPixmap::fromImage(image.scaled(imageSize.width(), imageSize.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    pixmap.setDevicePixelRatio(this->devicePixelRatioF());
    this->setFixedSize(imageSize);
    this->setIconSize(imageSize);
    this->setIcon(QIcon(pixmap));

    imageLoaded = true;
}

void ImageMessageItem::updateImageSize()
{
    int minVal = 100, maxVal = 300;
    if(image.width() > image.height()) {
        imageSize.setWidth(maxVal);
        imageSize.setHeight(maxVal * image.height() / image.width());

        if(imageSize.height() < minVal) {
            imageSize.setHeight(minVal);
        }
        if(imageSize.height() > maxVal) {
            imageSize.setHeight(maxVal);
        }
    } else {
        // 与上述推理同理
        imageSize.setHeight(maxVal);
        imageSize.setWidth(maxVal * image.width() / image.height());

        if(imageSize.width() < minVal) {
            imageSize.setWidth(minVal);
        }
        if(imageSize.width() > maxVal) {
            imageSize.setWidth(maxVal);
        }
    }

    qreal dpr = this->devicePixelRatioF();
    imageSize.setWidth(int(imageSize.width() / dpr));
    imageSize.setHeight(int(imageSize.height() / dpr));
}


/* ====================================== *
 *           文件消息类接口实现              *
 * ====================================== */
FileMessageItem::FileMessageItem(const QString& fileId, const QByteArray& content, const QString& fileName)
    : fileId(fileId), content(content), fileName(fileName), loadDone(false)
{
    // 1.文本框属性设置
    this->setFixedWidth(470);
    this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    this->setWordWrap(true);   // 自动换行
    this->setText("[文件] " + fileName);

    QFontMetrics metrics(this->font());
    QRect textRect = metrics.boundingRect(
        0, 0, this->width(), 0,
        Qt::TextWordWrap | Qt::AlignLeft,
        this->text()
        );
    int lineHeight = metrics.lineSpacing();            // 单行文本的实际行高（包含行间距）
    int actualLines = textRect.height() / lineHeight;

    this->setFixedHeight(16 * actualLines + 2);
    this->setContentsMargins(0, 2, 0, 0);   //通过文本框内自身的边距来控制与nameLabel的间距

    // 2.网络获取文件内容
    if(!content.isEmpty()) {
        return;
    }
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    connect(dataCenter, &model::DataCenter::getSingleFileDone, this, &FileMessageItem::getSingleFileDoneHandle, Qt::UniqueConnection);
    dataCenter->getSingleFileAsync(fileId);
}

void FileMessageItem::mousePressEvent(QMouseEvent* event)
{
    Q_UNUSED(event);
    if(!this->loadDone) {
        Toast::showMessage("数据尚未加载完毕, 请稍后重试");
        return;
    }
    QString filePath = QFileDialog::getSaveFileName(this, "另存为", QDir::homePath(), "*");
    if(filePath.isEmpty()) {
        return;
    }
    utils::FileUtil::writeByteArrayToFile(filePath, this->content);
}

void FileMessageItem::getSingleFileDoneHandle(const QString& fileId, const QByteArray& content)
{
    if(this->fileId != fileId) {
        return;
    }
    this->content = content;
    this->loadDone = true;
}

/* ====================================== *
 *           语音消息类接口实现              *
 * ====================================== */
SpeechMessageItem::SpeechMessageItem(const QString& fileId, const QByteArray& content)
    : fileId(fileId), content(content), loadDone(false)
{
    this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    this->setText("[语音]");

    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    connect(dataCenter, &model::DataCenter::getSingleFileDone, this, &SpeechMessageItem::getSingleFileDoneHandle, Qt::UniqueConnection);
    dataCenter->getSingleFileAsync(fileId);
}

void SpeechMessageItem::mousePressEvent(QMouseEvent* event)
{
    Q_UNUSED(event);
    if(!this->loadDone) {
        Toast::showMessage("数据尚未加载完毕, 请稍后重试");
        return;
    }
    SpeechRecorder* speechRecorder = SpeechRecorder::getInstance();
    speechRecorder->startPlay(this->content);
}

void SpeechMessageItem::getSingleFileDoneHandle(const QString &fileId, const QByteArray &content)
{
    if(this->fileId != fileId) {
        return;
    }
    this->content = content;
    this->loadDone = true;
}
